home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
121_01
/
tel.c
< prev
next >
Wrap
Text File
|
1985-08-19
|
23KB
|
1,118 lines
/*
HEADER: CUG 121.??;
TITLE: tel - dumb terminal + file xfer;
VERSION: 1.0;
DATE: 01/06/86;
DESCRIPTION: "Tel is a considerably modified version of Telnet v2.3, as
distributed with v1.46 of the BDS C compiler. The following
features have been added: multiple files may be transmitted or
received by one command, directories may be listed, and the
quit command hangs up a hayes smartmodem. To accommodate
these changes, some of the command names have been changed.
This program uses a modem to emulate a dumb terminal.
Incoming data may be buffered in memory and written to disk,
data may be transmitted from disk to the modem, or files may
be formally transferred in a "checksum" mode with automatic
handshaking and buffering.";
KEYWORDS: terminal, modem, emulate, file transfer;
SYSTEM: CP/M;
FILENAME: TEL.C;
WARNINGS: "Requires local.c and files.c for link.
The checksum file transfer does not follow the XMODEM
protocol.
Variable baud rate support is present, but commented out
(hardware-specific coding would be required to implement it).
Tel assumes that the CP/M console is much faster than the
modem (e.g. a 1200+ baud console with a 300 baud modem).";
SEE-ALSO: CALL.C, TELNET.C, TL370.C;
AUTHORS: Leor Zolman, Leo Kenen, Cal Thixton, Mike W. Meyer;
COMPILERS: BDS-C 1.50;
*/
#include <bdscio.h> /* System, h'ware constants */
#include <hardware.h>
#ifdef MULL /* muellers version if MULL is defined. */
#define TITLE "Mulltel version 1.5 12/3/80 tj"
#define INITB 3 /* 1200 baud initially */
#define SSPECIAL '\\' /* escape character initially */
#else
#define TITLE "Telnet version 3.0-Intersystems 10/25/80 (mwm)\n"
#define SSPECIAL 29 /* Initial escape character ^] */
#define INITB 5 /* 4800 baud initially. See setbaud() */
#endif
#define SELDSK 14 /* change logged in disk */
#define DIRFRST 17 /* search for first occurance of a file */
#define DIRNEXT 18 /* search for next occurance of a file */
#define CURRDSK 25 /* return currently logged in disk */
#define maxfiles 64 /* maximun # of file to send as once */
/*
The following #defines need not be changed:
*/
#define ACK 0x06 /* Ascii ACK for handshaking */
#define NAK 0x15
#define EOT 0x04 /* End of transmission */
#define ETX 0x03 /* Abort Transmission */
#define STX 0x02 /* Beginning of next filename to send */
#define NUL 0x0 /* end of file name */
#define PHA 0xfd /* for phase checking */
#define CR 0x0d /* carriage return */
#define LF 0x0a /* line feed */
#define NL '\n' /* god knows, compiler dependent! */
/*
File Control Block structure
*/
struct FCB {
char entry, /* entry type. assumed 0 */
name[8], /* file name */
type[3], /* file type */
extent, /* which entention is this one? */
na,naa, /* not used (??) */
count, /* record count */
map[16], /* disk allocation map */
next; /* next record to read */
};
/*
External variable declarations:
*/
char SPECIAL; /* current SPECIAL or escape character */
char rflag; /* receiving file open flag */
char tflag; /* transmitting file open flag */
char chflag; /* checksumming enabled flag */
char cflag; /* text-collection enabled flag */
char pflag; /* pausing flag */
char spflag; /* stripping parity bit flag */
char nflag; /* recognizing nulls flag */
char fflag; /* true if changing CR-LF's into
just CR when transmitting */
char lastc; /* last char transmitted */
char dodflag; /* true if displaying outging data */
char didflag; /* true if displaying incoming data */
char hdflag; /* true if effectively working in half-duplex */
char hd_sav; /* save flag when transmitting or receiving */
char abortf; /* true when file I/O aborted */
char rbuf[BUFSIZ]; /* file I/O buffer for incoming data file */
char tbuf[SECSIZ]; /* sector buffer for file being transmitted */
char tmp[20]; /* tempory holding place for file name */
char rname[20]; /* name of receiving file */
char tname[20]; /* name of transmitting file */
int rfd, tfd; /* file descriptors */
char *cptr; /* pointer to free space in buf */
unsigned free; /* number of bytes free in buf */
int bcount; /* counts bytes in current block when checksumming */
int scount; /* Number of sectors sent/received */
int checksum; /* the checksum value itself */
char timoutf; /* 1 if time-out happens while waiting for modem data*/
char *i; /* odd-job char pointer */
int dod_sav, did_sav; /* scratch variables */
unsigned bufspace; /* # of bytes available for collection buffer in ram */
char toupper(); /* This makes for better code */
char fcb[34]; /* file control block */
struct { /* so i can't use initializers */
char rate[5], /* readable baud rate */
hex;
} bauds [7];
char current; /* current baud rate being used */
char files[maxfiles][17]; /* files to send */
char leftover; /* number of file to send */
char thisdisk; /* currently logged in disk */
char *buf; /* text collection pointer; will
point to the location just after itself */
/*
place for main.c
*/
main()
{
char c, c2;
int n;
init();
while(1) {
if (abortf) {
if (rflag)
rclose();
if (tflag)
tabort();
reset();
abortf = 0;
}
if (tflag && xmit()) {
printf("\nTransmission complete.\n");
close(tfd);
reset();
}
if (abortf)
continue;
if (miready()) {
c = c2 = getmod();
if (spflag)
c &= 0x7f;
if (tflag && (c == ETX)) {
printf("Receiver has aborted;\n");
abortf = 1;
continue;
}
if (didflag && (c || nflag) && (c != CPMEOF))
display(c);
if (cflag && !pflag) {
if (c || nflag)
if (!free) {
printf("**BUFFER FULL**\007\007");
rdump(0);
}
else {
*cptr++ = c;
free--;
}
if (chflag) {
checksum += c2;
bcount++;
if (bcount == SECSIZ) {
bcount = 0;
outmod(checksum >> 8);
outmod(checksum);
checksum = 0;
c = getmod();
if(c == STX) {
getname(tmp);
rdump(0);
rclose();
scount=0;
strcpy(rname,tmp);
if(opento()) {
outmod(ETX);
abortf=1;
}
outmod(PHA);
}
else if (c == EOT) {
rdump(0);
rclose();
reset();
printf("\n%s received OK\n",rname);
}
else if (c == ACK) {
if (cptr > buf+1000)
rdump(0);
if (!didflag)
printf("-%d",++scount);
outmod(PHA);
}
else {
cptr -= SECSIZ;
free += SECSIZ;
printf("\nChecksum error. Retrying <%d>\n",scount+1);
outmod(PHA);
timoutf = 0;
}
}
}
}
}
if (kbready()) {
c = getch();
if (c != SPECIAL) {
if (pflag || (!tflag && !(rflag && chflag))) {
outmod(c);
if (dodflag)
display(c);
}
}
else special();
}
}
}
/*
place for special.c
*/
/*
Handle special Telnet command:
*/
special()
{
char c;
int nn,n;
printf("\n?: ");
if ( (c = getchar()) != NL) printf("...");
if(c==SPECIAL) {
outmod(SPECIAL);
printf("Current Escape 0x%02x sent", SPECIAL) ;
}
else switch (toupper(c)) {
case 'E' :
printf("Current Escape Character: 0x%02x\n",SPECIAL);
printf("Enter New Escape Character: ");
SPECIAL=getchar();
putchar(NL);
break;
case '7':
spflag = ask("Strip parity");
break;
case 'B':
dobauds();
break;
case 'N':
nflag = ask("Recognize incoming nulls");
break;
case 'F':
fflag = ask("Transmit CR-LF pairs as CR only");
break;
case 'H':
if (rflag || tflag) {
printf("Must abort transfer first\n");
break;
}
hd_sav = hdflag = ask ("Half Duplex");
reset();
break;
case 'Z':
puts(CLEARS) ;
break;
case 'P':
if (pflag)
printf("Already pausing");
else if (!(tflag || rflag)